#include "dynamicmodel.h"

///////// ObjectsIndex /////////////////////////////////////////////////////////////////////////////

ObjectsIndex::ObjectsIndex( QObject * parent )
    : QObject(parent)
{
}

ObjectsIndex::~ObjectsIndex()
{
}

ARSDummyForm * ObjectsIndex::addForm( QString name, ARSExecItem * item  )
{
    ARSDummyForm * form = 0;
    ARSDummyObject * object = findObject(name, ARSObject::Form);

    if(!object)
    {
        form = new ARSDummyForm();
        form->setName(name);
        m_objectsList.append(form);
        object = form;
    }

    if(item)
        addRelation(object, item);

    return static_cast<ARSDummyForm *>(object);
}

ARSDummyField * ObjectsIndex::addField( ARSDummyForm * form, QString name, int id, ARSExecItem * item )
{
    ARSDummyField * field = const_cast<ARSDummyField *>(form->field(name));

    if(field)
        return field;

    field = new ARSDummyField(form);
    field->setName(name);
    field->setID(id);
    form->appendField(field);
    m_objectsList.append(field);

    if(item)
        addRelation(field, item);
    else
        qDebug("ObjectsIndex::addField: bug!");

    return field;
}

ARSDummyActiveLink * ObjectsIndex::addActiveLink( QString name, ARSExecItem * item )
{
    ARSDummyActiveLink * activeLink = 0;
    ARSDummyObject * object = findObject(name, ARSObject::ActiveLink);

    if(!object)
    {
        activeLink = new ARSDummyActiveLink();
        activeLink->setName(name);
        m_objectsList.append(activeLink);
        object = activeLink;
    }

    if(item)
        addRelation(object, item);

    return static_cast<ARSDummyActiveLink *>(object);
}

ARSDummyFilter * ObjectsIndex::addFilter( QString name, ARSExecItem * item )
{
    ARSDummyFilter * filter = 0;
    ARSDummyObject * object = findObject(name, ARSObject::Filter);

    if(!object)
    {
        filter = new ARSDummyFilter();
        filter->setName(name);
        m_objectsList.append(filter);
        object = filter;
    }

    if(item)
        addRelation(object, item);

    return static_cast<ARSDummyFilter *>(object);
}

ARSDummyGuide * ObjectsIndex::addGuide( QString name, ARSExecWorkflowObject::ObjectType objectsType,
                                        ARSExecItem * item )
{
    ARSDummyGuide * guide = 0;
    ARSDummyObject * object = findObject(name, ARSObject::Guide, 0, objectsType);

    if(!object)
    {
        guide = new ARSDummyGuide(objectsType);
        guide->setName(name);
        m_objectsList.append(guide);
        object = guide;
    }

    if(item)
        addRelation(object, item);

    return static_cast<ARSDummyGuide *>(object);
}

ARSDummyObjectList ObjectsIndex::objects( ARSObject::Types types ) const
{
    ARSDummyObjectList list;

    foreach(ARSDummyObject * object, m_objectsList)
        if(object->type() & types)
            list.append(object);

    return list;
}

ARSDummyObjectList & ObjectsIndex::objects()
{
    return m_objectsList;
}

void ObjectsIndex::clear()
{
    m_objectsList.clear();
}

void ObjectsIndex::addRelation( ARSDummyObject * object, ARSExecItem * item )
{
    if(!m_objectsHash.values(object).contains(item))
        m_objectsHash.insertMulti(object, item);
}

ARSExecItemList ObjectsIndex::relatedItems( ARSDummyObject * object ) const
{
    return m_objectsHash.values(object);
}

ARSDummyObject * ObjectsIndex::findObject( const QString & name, ARSObject::Type type,
                                           ARSDummyForm * parentForm, ARSExecWorkflowObject::ObjectType objectsType ) const
{
    foreach(ARSDummyObject * object, m_objectsList)
    {
        if(object->type() == type)
        {
            if(type == ARSObject::Field)
            {
                ARSDummyField * field = static_cast<ARSDummyField *>(object);
                if(field->parentForm() == parentForm && field->name() == name)
                {
                    return field;
                }
            }
            else
            {
                if(type == ARSObject::Guide)
                {
                    ARSDummyGuide * guide = static_cast<ARSDummyGuide *>(object);
                    if(guide->name() == name && guide->objectsType() == objectsType)
                        return guide;
                }
                else
                    if(object->name() == name)
                        return object;
            }
        }
    }

    return 0;
}

bool ObjectsIndex::contains( ARSDummyObject * object, bool primaryOnly ) const
{
    if(!object)
        return false;

    foreach(ARSDummyObject * myObject, m_objectsList)
    {
            if (*myObject == *object &&
                (primaryOnly && myObject->status() == ARSDummyObject::Primary || !primaryOnly))
                return true;
    }

    return false;
}

///////// DynamicModel /////////////////////////////////////////////////////////////////////////////

DynamicModel::DynamicModel(ARSExecModelRootItem * rootItem, QObject * parent)
    : QObject(parent)
{
    m_rootItem = rootItem;
    m_index = new ObjectsIndex(this);
}

ARSExecModelRootItem * DynamicModel::rootItem()
{
    return m_rootItem;
}

ObjectsIndex * DynamicModel::index() const
{
    return m_index;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
